package com.study.aop.aop;

import com.alibaba.fastjson.JSON;
import com.study.aop.entity.common.ResponseEntity;
import jdk.nashorn.internal.scripts.JO;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;

/**
 * @author flwu
 * @date 2020/3/19 4:12 PM
 * @MOTTO 保持空杯和敬畏
 */
@Aspect
@Component
public class ControllerLogAop {

    @Pointcut("execution(public * com.study.aop.controller.*.*(..))")
    public void webLog() {

    }

    /**
     * 切面的前行为
     * @param joinPoint
     */
    @Before("webLog()")
    public void doBefore(JoinPoint joinPoint) {
        System.out.println("start do before function");
        //获取目标方法的参数
        Object[] objects = joinPoint.getArgs();
        System.out.println("请求参数:" + objects);
        //代理
        Signature signature = joinPoint.getSignature();
        //代理的是哪个方法
        String funName = signature.getName();
        System.out.println("代理方法：" + funName);
        //代理的包名
        String packageName = signature.getDeclaringTypeName();
        System.out.println("代理的包名：" + packageName);
        //代理的类信息
        signature.getDeclaringType();
        MethodSignature methodSignature = (MethodSignature) signature;
        String[] strings = methodSignature.getParameterNames();
        System.out.println("参数名："+ Arrays.toString(strings));
        System.out.println("参数值ARGS : " + Arrays.toString(joinPoint.getArgs()));
        // 接收到请求，记录请求内容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest req = attributes.getRequest();
        // 记录下请求内容
        System.out.println("请求URL : " + req.getRequestURL().toString());
        System.out.println("HTTP_METHOD : " + req.getMethod());
        System.out.println("IP : " + req.getRemoteAddr());
        System.out.println("CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
    }

    /**
     * 切面的后行为，相当于returning 和throwing两个的功能
     * @param joinPoint
     */
    @After("webLog()")
    public void doAfter(JoinPoint joinPoint) {
        System.out.println("start do after function");
    }

    /**
     * 切面的后行为，当切面方法返回异常时执行
     * @param joinPoint
     */
    @AfterThrowing("webLog()")
    public void doAfterThrowing(JoinPoint joinPoint) {
        System.out.println("start do afterThrowing function");
    }

    /**
     * 切面的后行为，当切面方法正常返回时执行
     */
    @AfterReturning(pointcut = "webLog()", returning = "result")
    public void doAfterReturning(Object result) {
        System.out.println("start do afterReturning function");
        System.out.println("方法返回的内容:" + JSON.toJSONString(result));
    }

    /**
     * 切面的环绕方法  ---- 切记一定要有返回值， 否则会阻塞主方法
     * @param proceedingJoinPoint
     *
     */
    @Around("webLog()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) {
        try {
            System.out.println("start do around function");
            //该方法一定要调用，否则执行方法会阻塞， 该方法相当于出让程序控制权
            Object o = proceedingJoinPoint.proceed();
            return o;
        } catch (Throwable e) {
            e.printStackTrace();
            return null;
        }
    }
}
